package main

import (
	"fmt"
	"sync"
)

// go-routine + channel 实现多线程统计素数
var wg sync.WaitGroup

// 传数据
func putNum(intChan chan int) {
	for i := 2; i < 1000000; i++ {
		intChan <- i
	}
	close(intChan)
	wg.Done()

}

// 判断素数  并填到数据管道
func primeNum(intChan chan int, primeChan chan int, exitChan chan bool) {
	for v := range intChan {
		var flag = true
		for num := 2; num < v; num++ {
			if v%num == 0 {
				flag = false
				break
			}
		}
		if flag {
			primeChan <- v
		}
	}
	// close(primeChan) // 不能写在这里， 如果出现一个协程未结束被关闭管道，会导致写数据失败 throw exception
	exitChan <- true //  引入新的 channel 统计线程数量值，进行关闭
	wg.Done()
}

// 判断 判断素数方法 是否全部执行完毕
func exitC(exitChan chan bool, primeChan chan int) {
	for i := 0; i < 16; i++ {
		<-exitChan
	}
	close(primeChan)
	wg.Done()
}

// 取出结果数据
func outNum(primeChan chan int) {
	for v := range primeChan {
		fmt.Println(v)
	}
	wg.Done()
}

func main() {
	intChan := make(chan int, 1000)
	primeChan := make(chan int, 500000)
	exitChan := make(chan bool, 16)
	wg.Add(1)
	go putNum(intChan)

	for i := 0; i < 16; i++ {
		wg.Add(1)
		go primeNum(intChan, primeChan, exitChan)
	}
	wg.Add(1)
	go outNum(primeChan)

	wg.Add(1)
	go exitC(exitChan, primeChan)
	wg.Wait()
}
